package com.sugree.base;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.ChoiceFormat;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Color;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.AsyncTask;
import android.os.Parcelable;
import android.text.format.Time;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.sugree.util.entity.Message;
import com.sugree.util.FeedHelper;

public class BreakingNewsUpdateService {
	private static final String TAG = "BreakingNewsUpdateService";

	private static final String CACHE_FILE = "items.xml";

	public static final int MSG_CHANGED = 1;
	public static final int MSG_NOT_CHANGED = 2;

	protected int mItemIndex = 0;
	protected List<Message> items = null;

	protected Context mContext;
	protected Handler mHandler;
	protected Class mWidgetClass;
	protected Class mListClass;
	protected Class mItemClass;
	private String mFeedUrl;
	private String mEncoding;
	private int mTemplateUserAgent;
	private int mNotificationFormat;
	private int mNotificationSingular;
	private int mNotificationPlural;
	private int mNotificationIcon;
	private int mNotificationTitle;
	private int mWidget;
	private int mTitle;
	private int mLogo;

	private boolean mNotification;
	private boolean mVibration;
	private String mRingtone;

	public BreakingNewsUpdateService(Context context, Handler handler, Class widgetClass, Class listClass, Class itemClass, String url, String encoding, int tUA, int nFormat, int nSingular, int nPlural, int nIcon, int nTitle, int widget, int title, int logo) {
		mContext = context;
		mHandler = handler;
		mWidgetClass = widgetClass;
		mListClass = listClass;
		mItemClass = itemClass;
		mFeedUrl = url;
		mEncoding = encoding;
		mTemplateUserAgent = tUA;
		mNotificationFormat = nFormat;
		mNotificationSingular = nSingular;
		mNotificationPlural = nPlural;
		mNotificationIcon = nIcon;
		mNotificationTitle = nTitle;
		mWidget = widget;
		mTitle = title;
		mLogo = logo;

		restoreCache();
	}

	public void onStart(Intent intent, int startId, boolean notification, boolean vibration, String ringtone) {
		mNotification = notification;
		mVibration = vibration;
		mRingtone = ringtone;

		NotificationManager nm = (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
		nm.cancelAll();

		new UpdateTask().execute(intent);
	}

	public void onStop() {
		saveCache();
		items = null;
	}
	
	public void saveCache() {
		try {
			ObjectOutputStream os = new ObjectOutputStream(mContext.openFileOutput(CACHE_FILE, mContext.MODE_PRIVATE));
			os.writeObject(items);
			os.close();
		} catch (Exception ex) {
			Log.d(TAG, "saveCached() failed", ex);
		}
	}

	public void restoreCache() {
		try {
			ObjectInputStream is = new ObjectInputStream(mContext.openFileInput(CACHE_FILE));
			items = (List<Message>)is.readObject();
			is.close();
			/*
			Log.d(TAG, items.toString());
			Message m = items.get(0);
			Log.d(TAG, items.size()+" "+m.getTitle());
			Log.d(TAG, m.getLink());
			*/
		} catch (Exception ex) {
			Log.d(TAG, "restoreCached() failed", ex);
		}
	}

	public void process(Intent intent) {
		boolean isReload = intent.getBooleanExtra("reload", true);
		if (isReload || items == null) {
			int newItems = reload(mContext);
			mItemIndex = 0;

			if (newItems > 0) {
				notify(mContext, newItems);
				mHandler.sendEmptyMessage(MSG_CHANGED);
			} else {
				mHandler.sendEmptyMessage(MSG_NOT_CHANGED);
			}
		}

		RemoteViews updateViews = buildUpdate(mContext);
		mItemIndex = (mItemIndex+1)%items.size();

		ComponentName thisWidget = new ComponentName(mContext, mWidgetClass);
		AppWidgetManager manager = AppWidgetManager.getInstance(mContext);
		manager.updateAppWidget(thisWidget, updateViews);
	}

	public int reload(Context context) {
		int count = 0;
		try {
			String latestLink = "";

			if (items != null && items.size() > 0) {
				latestLink = items.get(0).getLink();
			}
			FeedHelper helper = new FeedHelper(context, mTemplateUserAgent, mEncoding);
			items = helper.getRSSContent(mFeedUrl);
			//items = helper.getRSSContent(getResources().openRawResource(R.raw.x));
			for(count=0; count<items.size(); count++) {
				if (items.get(count).getLink().equals(latestLink)) {
					break;
				}
			}
		} catch (FeedHelper.ApiException e) {
			Log.e(TAG, "Couldn't contact API", e);
		} catch (FeedHelper.ParseException e) {
			Log.e(TAG, "Couldn't parse API response", e);
		} catch (RuntimeException e) {
			Log.e(TAG, "Runtime", e);
		} catch (Exception e) {
			Log.e(TAG, "Unknown", e);
		}
		return count;
	}

	public void notify(Context context, int number) {
		if (!mNotification) {
			return;
		}

		MessageFormat form = new MessageFormat(mContext.getText(mNotificationFormat).toString());
		Object[] formArgs = new Object[] { number };
		double[] itemLimits = { 1, 2 };
		String[] itemPart = {
			mContext.getText(mNotificationSingular).toString(),
			mContext.getText(mNotificationPlural).toString()};
		ChoiceFormat itemForm = new ChoiceFormat(itemLimits, itemPart);
		form.setFormatByArgumentIndex(0, itemForm);
		String message = form.format(formArgs);

		NotificationManager nm = (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
		Notification n = new Notification(mNotificationIcon, message, System.currentTimeMillis());

		n.vibrate = null;
		if (mVibration) {
			n.vibrate = new long[] { 200, 300, 200, 300 };
		}

		n.flags = Notification.FLAG_SHOW_LIGHTS | Notification.FLAG_AUTO_CANCEL;
		n.ledOffMS = 1000;
		n.ledOnMS = 500;
		n.ledARGB = Color.GREEN;

		n.sound = null;
		if (mRingtone != null && !mRingtone.equals("")) {
			n.sound = Uri.parse(mRingtone);
		}

		n.number = number;
		PendingIntent intent = PendingIntent.getActivity(mContext, number, new Intent(mContext, mListClass), 0);
		n.setLatestEventInfo(mContext, mContext.getText(mNotificationTitle), message, intent);

		nm.notify(1, n);
	}

	public RemoteViews buildUpdate(Context context) {
		RemoteViews updateViews = null;

		Message m = items.get(mItemIndex);
		updateViews = new RemoteViews(context.getPackageName(), mWidget);
		updateViews.setTextViewText(mTitle, m.getTitle());

		Intent intent = new Intent(context, mContext.getClass());
		intent.putExtra("reload", false);
		PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
		updateViews.setOnClickPendingIntent(mTitle, pendingIntent);

		/*
		intent = new Intent(Intent.ACTION_VIEW);
		intent.setData(Uri.parse(m.getLink()));
		*/
		intent = new Intent(context, mItemClass);
		intent.putExtra("item", (Parcelable)m);
		intent.setData(Uri.parse(m.getLink().toString()));
		pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
		updateViews.setOnClickPendingIntent(mLogo, pendingIntent);
		return updateViews;
	}

	private class UpdateTask extends AsyncTask<Intent, Integer, Exception> {
		protected Exception doInBackground(Intent... intent) {
			try {
				BreakingNewsUpdateService.this.process(intent[0]);
			} catch (Exception e) {
				Log.e(TAG, e.toString());
				return e;
			}
			return null;
		}

		protected void doProgressUpdate(Integer... progress) {
		}

		protected void doPostExecute(Exception e) {
			if (e != null) {
				Toast.makeText(BreakingNewsUpdateService.this.mContext, e.toString(), Toast.LENGTH_SHORT);
			}
			((Service)mContext).stopSelf();
		}
	}

	public List<Message> getItems() {
		return items;
	}
}
